package wuziqi;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * 五子棋游戏面板类
 * 负责棋盘绘制、鼠标事件处理、游戏逻辑控制和AI对战功能
 */
public class pan extends JPanel implements MouseListener {
    // 棋盘行列数（15x15标准棋盘）
    int row = 15;
    int col = 15;
    // 棋盘图片文件名
    String qipan_name = "qipan1.jpg";
    // 玩家棋子图片文件名（通常为黑色）
    String qizi1_name = "c1.png";
    // 电脑棋子图片文件名（通常为白色）
    String qizi2_name = "c2.png";
    // 棋盘状态数组（0=空位，1=玩家棋子，2=电脑棋子）
    int num[][] = new int[row][col];
    // 游戏状态标记（是否可以落子）
    boolean canSetqizi = true;
    // 已落子数
    int qizi_num = 0;
    // 排行榜数据列表
    List<paihangbang> paihanglist;
    // 记录当前鼠标点击的位置
    private int currentX, currentY;

    /**
     * 面板构造方法
     * 初始化游戏数据并注册鼠标监听器
     */
    public pan() {
        // 加载排行榜数据
        paihanglist = FileStorageUtil.loadRankings();
        // 添加鼠标事件监听器
        addMouseListener(this);
    }

    /**
     * 绘制面板内容
     * 负责绘制棋盘和棋子
     * @param g 图形上下文对象
     */
    public void paint(Graphics g) {
        super.paint(g);
        // 加载并绘制棋盘图片
        Image img = new ImageIcon("img/" + qipan_name).getImage();
        g.drawImage(img, 0, 0, 567, 567, this);

        // 加载玩家和电脑的棋子图片
        Image c1 = new ImageIcon("img/" + qizi1_name).getImage();
        Image c2 = new ImageIcon("img/" + qizi2_name).getImage();

        // 遍历棋盘数组，绘制所有棋子
        for (int i = 0; i < num.length; i++) {
            for (int j = 0; j < num[i].length; j++) {
                if (num[i][j] == 1) {
                    // 绘制玩家棋子
                    g.drawImage(c1, i * 35 + 20, j * 35 + 20, 35, 35, this);
                } else if (num[i][j] == 2) {
                    // 绘制电脑棋子
                    g.drawImage(c2, i * 35 + 20, j * 35 + 20, 35, 35, this);
                }
            }
        }
    }

    /**
     * 获取电脑落子位置
     * 实现简单的AI逻辑：优先防守，其次进攻，最后随机落子
     * @param x 玩家落子的x坐标
     * @param y 玩家落子的y坐标
     * @return 电脑落子的坐标数组，格式为[int{x}, int{y}]，若无合适位置则返回null
     */
    public int[] getLoc(int x, int y) {
        // 检查玩家威胁，优先防守
        int[] defense = checkThreat(x, y, 1);
        if (defense != null) {
            return defense;
        }

        // 检查电脑自身连子，寻找进攻机会
        int[] attack = checkThreat(x, y, 2);
        if (attack != null) {
            return attack;
        }

        // 没有明显威胁或进攻机会时随机落子
        return null;
    }

    /**
     * 检查指定位置的威胁情况
     * 用于AI的防守和进攻判断
     * @param x 检查的起始x坐标
     * @param y 检查的起始y坐标
     * @param player 检查的玩家类型（1=玩家，2=电脑）
     * @return 最佳落子位置数组，格式为[int{x}, int{y}]，若无合适位置则返回null
     */
    private int[] checkThreat(int x, int y, int player) {
        // 横向检查
        int count = 1;
        int[] left = null, right = null;

        // 向左检查连子
        for (int i = x - 1; i >= 0; i--) {
            if (num[i][y] == player) {
                count++;
            } else {
                // 记录左侧空位
                if (num[i][y] == 0) {
                    left = new int[]{i, y};
                }
                break;
            }
        }

        // 向右检查连子
        for (int i = x + 1; i < row; i++) {
            if (num[i][y] == player) {
                count++;
            } else {
                // 记录右侧空位
                if (num[i][y] == 0) {
                    right = new int[]{i, y};
                }
                break;
            }
        }

        // 若连子数≥3，返回最佳防守/进攻位置
        if (count >= 3) {
            if (left != null) return left;
            if (right != null) return right;
        }

        // 纵向检查（逻辑与横向类似）
        count = 1;
        int[] up = null, down = null;

        for (int j = y - 1; j >= 0; j--) {
            if (num[x][j] == player) {
                count++;
            } else {
                if (num[x][j] == 0) {
                    up = new int[]{x, j};
                }
                break;
            }
        }

        for (int j = y + 1; j < col; j++) {
            if (num[x][j] == player) {
                count++;
            } else {
                if (num[x][j] == 0) {
                    down = new int[]{x, j};
                }
                break;
            }
        }

        if (count >= 3) {
            if (up != null) return up;
            if (down != null) return down;
        }

        // 左上右下对角线检查
        count = 1;
        int[] upLeft = null, downRight = null;

        for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) {
            if (num[i][j] == player) {
                count++;
            } else {
                if (num[i][j] == 0) {
                    upLeft = new int[]{i, j};
                }
                break;
            }
        }

        for (int i = x + 1, j = y + 1; i < row && j < col; i++, j++) {
            if (num[i][j] == player) {
                count++;
            } else {
                if (num[i][j] == 0) {
                    downRight = new int[]{i, j};
                }
                break;
            }
        }

        if (count >= 3) {
            if (upLeft != null) return upLeft;
            if (downRight != null) return downRight;
        }

        // 右上左下对角线检查
        count = 1;
        int[] upRight = null, downLeft = null;

        for (int i = x - 1, j = y + 1; i >= 0 && j < col; i--, j++) {
            if (num[i][j] == player) {
                count++;
            } else {
                if (num[i][j] == 0) {
                    upRight = new int[]{i, j};
                }
                break;
            }
        }

        for (int i = x + 1, j = y - 1; i < row && j >= 0; i++, j--) {
            if (num[i][j] == player) {
                count++;
            } else {
                if (num[i][j] == 0) {
                    downLeft = new int[]{i, j};
                }
                break;
            }
        }

        if (count >= 3) {
            if (upRight != null) return upRight;
            if (downLeft != null) return downLeft;
        }

        return null;
    }

    /**
     * 检查指定位置是否获胜
     * @param x 检查的x坐标
     * @param y 检查的y坐标
     * @return true表示获胜，false表示未获胜
     */
    public boolean iswin(int x, int y) {
        int currentPlayer = num[x][y];
        // 空位置不能获胜
        if (currentPlayer == 0) return false;

        int count;

        // 横向检查连子数
        count = 1;
        for (int i = x - 1; i >= 0 && num[i][y] == currentPlayer; i--) {
            count++;
        }
        for (int i = x + 1; i < row && num[i][y] == currentPlayer; i++) {
            count++;
        }
        if (count >= 5) return true;

        // 纵向检查连子数
        count = 1;
        for (int j = y - 1; j >= 0 && num[x][j] == currentPlayer; j--) {
            count++;
        }
        for (int j = y + 1; j < col && num[x][j] == currentPlayer; j++) {
            count++;
        }
        if (count >= 5) return true;

        // 左上右下对角线检查连子数
        count = 1;
        for (int i = x - 1, j = y - 1; i >= 0 && j >= 0 && num[i][j] == currentPlayer; i--, j--) {
            count++;
        }
        for (int i = x + 1, j = y + 1; i < row && j < col && num[i][j] == currentPlayer; i++, j++) {
            count++;
        }
        if (count >= 5) return true;

        // 右上左下对角线检查连子数
        count = 1;
        for (int i = x - 1, j = y + 1; i >= 0 && j < col && num[i][j] == currentPlayer; i--, j++) {
            count++;
        }
        for (int i = x + 1, j = y - 1; i < row && j >= 0 && num[i][j] == currentPlayer; i++, j--) {
            count++;
        }
        if (count >= 5) return true;

        return false;
    }

    /**
     * 鼠标点击事件处理
     * 处理玩家落子和电脑AI响应
     * @param e 鼠标事件对象
     */
    @Override
    public void mouseClicked(MouseEvent e) {
        // 游戏结束时不能落子
        if (!canSetqizi) return;

        int x = e.getX();
        int y = e.getY();

        // 计算棋盘上的行列位置（考虑棋盘边距和格子大小）
        int i = (x - 20) / 35;
        int j = (y - 20) / 35;

        // 检查坐标是否在有效范围内
        if (i < 0 || i >= row || j < 0 || j >= col) {
            return;
        }

        // 检查该位置是否已有棋子
        if (num[i][j] != 0) {
            JOptionPane.showMessageDialog(this, "该位置已有棋子，请重新选择！");
            return;
        }

        // 玩家落子（标记为1）
        num[i][j] = 1;
        qizi_num++;
        // 重绘面板显示新棋子
        repaint();

        // 检查玩家是否获胜
        if (iswin(i, j)) {
            JOptionPane.showMessageDialog(this, "恭喜，你赢了！");
            canSetqizi = false;

            // 添加到排行榜
            paihangbang ph = new paihangbang();
            ph.setJushu(paihanglist.size() + 1);
            ph.setBushu(qizi_num);
            ph.setJieguo("win");
            paihanglist.add(ph);

            // 保存到文件
            FileStorageUtil.saveRankings(paihanglist);
            return;
        }

        // 电脑思考延迟（增加游戏体验）
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        // 电脑落子
        int[] location = getLoc(i, j);
        if (location != null) {
            // 使用AI计算的最佳位置
            i = location[0];
            j = location[1];
        } else {
            // 随机找一个空位
            Random rand = new Random();
            do {
                i = rand.nextInt(row);
                j = rand.nextInt(col);
            } while (num[i][j] != 0);
        }

        num[i][j] = 2;
        qizi_num++;
        repaint();

        // 检查电脑是否获胜
        if (iswin(i, j)) {
            JOptionPane.showMessageDialog(this, "很遗憾，你输了！");
            canSetqizi = false;

            // 添加到排行榜
            paihangbang ph = new paihangbang();
            ph.setJushu(paihanglist.size() + 1);
            ph.setBushu(qizi_num);
            ph.setJieguo("fail");
            paihanglist.add(ph);

            // 保存到文件
            FileStorageUtil.saveRankings(paihanglist);
            return;
        }
    }

    // 以下为MouseListener接口的空实现方法
    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}
}